#pragma comment(lib, "crypt32.lib")

#include <stdio.h>
#include <tchar.h>		// _ftprintf
#include <windows.h>
//#include <Wincrypt.h>
#include <cstdio>
using namespace std;

//-------------------------------------------------------------------
// This example uses the function MyHandleError, a simple error
// handling function to print an error message and exit 
// the program. 
// For most applications, replace this function with one 
// that does more extensive error reporting.

void MyHandleError(LPTSTR psz)
{
	_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
	_ftprintf(stderr, TEXT("%s\n"), psz);
	_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
	_ftprintf(stderr, TEXT("Program terminating. \n"));
	exit(1);
} // End of MyHandleError.

void writeCertFile(DWORD i, LPBYTE pbCert, DWORD dwCertLen)
{
	FILE *ptr_fp;
	char nameFile[11] = {'c', 'e', 'r', 't', '0', 'x', '.', 'd', 'e', 'r', '\0'};
	char c = '0';
	if (i == 0)	c = '1';
	else if (i == 1) c = '2';
	else if (i == 2) c = '3';
	nameFile[5] = c;
	printf("name : %s\n", nameFile);
	if((ptr_fp = fopen(nameFile, "wb")) == NULL)
	{
		printf("Unable to open file!\n");
		return;
	}else printf("Opened file successfully for writing.\n");
	if( fwrite(pbCert, dwCertLen, 1, ptr_fp) != 1)
	{
		printf("Write error!\n");
		return;
	}else printf("Write was successful.\n");
	fclose(ptr_fp);
}

int main (int argc, char *argv[])
{
	printf("Hello dnie !!!\n");
	LPCTSTR			szReaderName			= NULL;
	LPTSTR			szMainContainerName		= NULL;
	BOOL			bStatus					= FALSE;
	HCRYPTPROV		HMainCryptProv			= NULL;
	LPCTSTR			szProviderName			= _T("Microsoft Base Smart Card Crypto Provider");
	DWORD			dwErr					= 0;
	CHAR			szContainerName[1024];
	DWORD			dwContainerNameLen		= sizeof(szContainerName);
	DWORD			dwFlags					= CRYPT_FIRST;
	DWORD			dwContextArrayLen		= 0;
	HCRYPTPROV		hProv					= NULL;
	DWORD			pKeySpecs[2]			= { AT_KEYEXCHANGE, AT_SIGNATURE };
	HCRYPTKEY		hKey					= NULL;
	DWORD			dwCertLen				= 0;
	LPBYTE			pbCert					= NULL;
	PCCERT_CONTEXT	pCertContext			= NULL;
	PCCERT_CONTEXT	pContextArray[128];

	if (szReaderName)
	{
		size_t ulNameLen = _tcslen(szReaderName);
		szMainContainerName = (LPTSTR) LocalAlloc(0, (ulNameLen + 6) * sizeof(TCHAR));
		if (!szMainContainerName)
		{
			return GetLastError();
		}
		//printf();
		printf(szMainContainerName, _T("\\\\.\\%s\\"), szReaderName);
	}

	bStatus = CryptAcquireContext(
		&HMainCryptProv,
		szMainContainerName,
		szProviderName,
		PROV_RSA_FULL,
		0);
	if (!bStatus)
	{
		dwErr = GetLastError();
		printf("dwErr = %x", dwErr);
		return -1;
	}

	// Enumerate the containers.
	DWORD i;
	for(i=0 ; ; i++)
	{
		if(!CryptGetProvParam(HMainCryptProv, PP_ENUMCONTAINERS, (LPBYTE) szContainerName, &dwContainerNameLen, dwFlags)) {

			if(GetLastError() == ERROR_NO_MORE_ITEMS) {
				// Exit the loop.
				printf("i = %d\n", i);		
				break;
			} else {
				printf("Error %x reading algorithm!\n", GetLastError());
				return 0;
			}
		}
		//printf("i = %d - %s\n", i, szContainerName);	// here container name exist

		if (CryptAcquireContext(
			&hProv,
			szContainerName,
			szProviderName,
			PROV_RSA_FULL,
			0))
		{
			printf("i = %d - %s\n", i, szContainerName);
			// Loop over all the key specs
			for (int j = 0; j < 2; j++)
			{
				printf("j  = %d\n", j);
				if (CryptGetUserKey(
					hProv,
					pKeySpecs[j],
					&hKey) )
				{
					if (CryptGetKeyParam(
						hKey,
						KP_CERTIFICATE,
						NULL,
						&dwCertLen,
						0))
					{
						pbCert = (LPBYTE) LocalAlloc(0, dwCertLen);
						if (!pbCert)
						{
							dwErr = GetLastError();
							//goto end:
							break;
						}
						if (CryptGetKeyParam(
							hKey,
							KP_CERTIFICATE,
							pbCert,
							&dwCertLen,
							0))
						{
							pCertContext = CertCreateCertificateContext(
								X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, 
								pbCert,
								dwCertLen);
							if (pCertContext)
							{
								char pbNameString[256];
								printf("dwContextArrayLen = %d\n", dwContextArrayLen);
								pContextArray[dwContextArrayLen++] = pCertContext;
								if (CertGetNameString(
									pCertContext,
									CERT_NAME_SIMPLE_DISPLAY_TYPE,
									0,
									NULL,
									pbNameString,
									128))
								{
									printf("Certificate Name : %s\n", pbNameString);
								}
							}
							// write cert file
							writeCertFile(i, pbCert, dwCertLen);
						}
						LocalFree(pbCert);
					}
					CryptDestroyKey(hKey);
					hKey = NULL;
				}
			}
			CryptReleaseContext(hProv, 0);
			hProv = NULL;
		}
		// prepare parameters for the next loop
		dwContainerNameLen = sizeof(szContainerName);
		dwFlags = 0;	// only Set the CRYPT_FIRST flag the first time through the loop.
	}
	return 0;
}